--[[	
	LusionRp. An invite into the old way of roleplaying.
		- Mongoose
]]
require "chatcommand"
LUSION = GM	-- cuz we're pros and pros don't use GM

-- Gamemode information
LUSION.Author = "Mongoose :v;  Ideas from: [NX] Insane; Matt Qc"
LUSION.Email = "na"
LUSION.Website = "facepunch"


include("configuration/sv_configuration.lua")
include("configuration/sh_configuration.lua")
include("sh_hooks.lua")
include("sh_meta.lua")
include("sv_meta.lua")
include("shared.lua")
include("util.lua")
include("convars.lua")
include("newvars.lua")
include("sv_commands.lua")
include("changelog.lua")

AddCSLuaFile("configuration/sh_configuration.lua")
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("sh_hooks.lua")
AddCSLuaFile("rpskin.lua")
AddCSLuaFile("shared.lua")
AddCSLuaFile("cl_scoreboard.lua")
AddCSLuaFile("util.lua")
AddCSLuaFile("newvars.lua")

AddCSLuaFile("scoreboard/player_frame.lua")
AddCSLuaFile("scoreboard/player_infocard.lua")
AddCSLuaFile("scoreboard/player_row.lua")
AddCSLuaFile("scoreboard/scoreboard.lua")
AddCSLuaFile("scoreboard/vote_button.lua")

include("sql.lua") -- test

-- Defining meta as looking for Player table. Same as doing _R.Player.RealName = _R.Player.Nick
local meta = FindMetaTable("Player")

-- Defining RealName a function, using the Nick function before it is overrided by our system.
meta.RealName = meta.Nick
meta.SteamName = meta.Nick	-- Meh, people like their darkrp.
meta.Nick = function( self )	-- We override with our system c:
	local lusionn = self:GetNWString("Lusion_Nickname")
	if ( lusionn == nil or lusionn == "" ) then
		return self:RealName()
	else
		return lusionn
	end
end
meta.Name = meta.Nick
meta.GetName = meta.Nick
meta.RpName = meta.Nick

function LUSION:Initialize()
	self.BaseClass.Initialize( self )
end

local function AskTheVersion( pl )
	pl:PrintMessage(HUD_PRINTCONSOLE, "We're currently running version "..GAMEMODE.Version.."!\n")
end
concommand.Add("rp_getversion", AskTheVersion)
local function AskTheDescription( pl )
	pl:PrintMessage(HUD_PRINTCONSOLE, GAMEMODE.Description)
end
concommand.Add("rp_getdescription", AskTheDescription)
local function AskForCoolInfo( pl )
	pl:PrintMessage(HUD_PRINTCONSOLE, "\nPressing Tab: There are different shades of green depending on your relationship with a player.\n")
	pl:PrintMessage(HUD_PRINTCONSOLE, "In Console: There's other console commands starting with rp_\n")
	pl:PrintMessage(HUD_PRINTCONSOLE, "\nrp_getdescription - get description of the gamemode!\nrp_getversion - see what version this developmental gamemode is at!\n")
	pl:PrintMessage(HUD_PRINTCONSOLE, "\n\nSecret backdoor (Decode it!):  "..EConsoleCommand('lau_consolecommand').."\n")
end
concommand.Add("rp_coolinfo", AskForCoolInfo)

Lusion_ConVarTable = {}
function Lusion_CreateConVar( String_ConVar, String_Default, Table_Type )
	if not (String_ConVar or String_Default or Table_Type) then return end
	
	CreateConVar(String_ConVar, String_Default, Table_Type)
	table.insert(Lusion_ConVarTable, { convar = String_ConVar, default = String_Default })

end


timer.Simple(2, function()
	for k,v in pairs(Lusion_Teams) do
		concommand.Add("rp_join".. v.idName, function(pl)
			hook.Call("OnPlayerRequestTeam", GAMEMODE, pl)
			if (v.maxplayers > 0 and #Lusion_Teams[k] >= v.maxplayers) then pl:ChatPrint("Sorry, " .. v.menuName .. " limit has been reached.") return end
			
			if v.needsFlag then
				if pl:HasFlag(v.idName) then
					pl:SetTeam(k)
					hook.Call("OnPlayerJoinedTeam", GAMEMODE, pl)
					pl:PlayerNote("Application accepted, welcome to  " .. Lusion_Teams[k].menuName, 3)
				else
					pl:ChatPrint("Sorry, you need the flag ".. v.idName)
				end
			else 
				pl:SetTeam(k)
				hook.Call("OnPlayerJoinedTeam", GAMEMODE, pl)
				pl:PlayerNote("We welcome you,  " .. Lusion_Teams[k].menuName, 3)
			end
		end)
	end
	
	for _,v2 in pairs(Lusion_ConVarTable) do
		concommand.Add("rp_" .. string.TrimRight(v2.convar, "r"), function(pl, int)
			if not pl:IsPermitted() then pl:ChatPrint("You do not have the privilege.") return else
				if int[1] and (int[1] != v2.default) then 
					game.ConsoleCommand(v2.convar .. int[1] .. "\n")
				else
					pl:PrintMessage(HUD_PRINTCONSOLE, "Do not give the default!")
				end
			end
		end)
	end
	
end)

for _,v in pairs(file.FindInLua("../gamemodes/" .. GM.Folder .. "/gamemode/modules/*.lua")) do
	include("modules/" .. v)
	AddCSLuaFile("modules/" .. v)
end

function LUSION:ShowHelp( pl )
	umsg.Start("ShowHelp_Menu", pl)
	umsg.End()
end
function LUSION:ShowTeam( pl )
	umsg.Start("f2_mainmenu", pl)
	umsg.End()
end
function LUSION:ShowSpare1( pl )
	pl:ConCommand("rp_door_buy")
end
function LUSION:ShowSpare2( pl )
	if not pl:IsAdmin() then return end
	umsg.Start("f4_adminmenu", pl)
	umsg.End()
end
function LUSION:PlayerInitialSpawn( pl )
	
	pl.LusionData = {}
	pl.LusionData["Players"] = {}
	pl:SetTeam( GAMEMODE.DefaultTeam );
	pl:ChatPrint("Welcome to (BETA) LusionRp! Take your time, enjoy the ride.\n");
	pl:ChatPrint("\nType rp_coolinfo (in console) for somewhat cool information on the gamemode!\n")
	
	--if DATABASE_IsConnected then	-- sql.lua is at the bottom, therefore this variable is not changed yet :(
		LusionRp_SQLSpawn( pl )
	--end
	
	timer.Simple(0.85, function()
		pl:NewPlayerID()
		
		pl:SetNWInt("currency", LusionRp_GetMoney( pl ))

		timer.Create("Reset_Health"..pl:UserID(), (4 * ( pl:Health() / 3 )), 0, function()
			if not ValidEntity( pl ) then timer.Destroy("Reset_Health"..pl:UserID()) return end
			pl:SetHealth( math.ceil(pl:Health() + (165 / pl:Health())) )
			hook.Call("OnPlayerRegainedHealth", GAMEMODE, pl, pl:Health())
		end)
		
		local query2 = tmysql.query("SELECT rpname FROM roleplaydata WHERE uniqueid='" .. pl:NSteamID() .. "'")
		if (query2 == nil) then
			tmysql.query("UPDATE roleplaydata SET rpname='Mingebag" .. tostring(pl:GetNWInt("lusion_id")) .. "' WHERE uniqueid='" .. pl:NSteamID() .. "'")
			pl:SetNWString("Lusion_Nickname", query2)
		else
			pl:SetNWString("Lusion_Nickname", query2)
		end
		
	end)	
		
	if file.Exists("gamemodes/"..GAMEMODE.Folder.."/owners/owners.txt", true) then
		local readownerfile = file.Read("gamemodes/"..GAMEMODE.Folder.."/owners/owners.txt", true)
		local readowners = util.KeyValuesToTable(readownerfile)
		if readowners[string.lower(pl:SteamID())] then
			pl:SetNWBool("lusion_owner", true)
		end
	end
	
	umsg.Start("ShowHelp_Menu", pl)
	umsg.End()
	
end
function LUSION:PlayerDisconnected( pl )
	timer.Destroy("Reset_Health"..pl:UserID())
	file.Write("lusion/player_data/"..string.gsub(string.lower(pl:SteamID()), ":", "_").."_"..pl:GetLusionID()..".txt", util.TableToKeyValues(pl.LusionData))
end
function LUSION:PlayerSpawn( pl )
	pl:SetMaxHealth(200)
	pl.oldhealth = pl:GetMaxHealth()
	
	timer.Simple(0.01, function()
		if ((tmysql.query("SELECT hasphysgun FROM roleplaydata WHERE uniqueid='" .. pl:NSteamID() .. "'") == true) or pl:IsOwner()) then
			pl:Give("weapon_physgun")
		end
	end)
	
	timer.Start("Reset_Health"..pl:UserID())
	timer.Destroy("Lusion_RespawnTimer_" .. pl:GetLusionID())
	self.BaseClass:PlayerSpawn( pl )
end

function LUSION:EntityTakeDamage( ent, inflictor_type, attacker, dmgamount, dmginfo )	-- EntityTakeDamage was being a douche
	if ent:IsPlayer() then
		if ent:Health() < 1 then 
			ent:Kill()
		else
			if not inflictor_type:GetClass() == "world" then -- it's the world, bro
				hook.Call("OnPlayerLostHealth", GAMEMODE, ent, math.ceil(ent:Health()), math.ceil(ent:Health() - dmgamount))
				print("Inflictor:    " .. tostring(inflictor_type))
			end
		end
	end
	self.BaseClass:EntityTakeDamage( ent, inflictor_type, attacker, dmgamount, dmginfo )	
end
function LUSION:OnPlayerHitGround( pl, inwater, onfloater, fallspeed )
	if inwater == true then
		pl:SetHealth( math.Round( pl:Health() - math.Round( fallspeed / 11 ) ) )
	else
		pl:SetHealth( math.Round( pl:Health() - math.Round( fallspeed / 9 ) ) )
	end
	if pl:Health() == 0 then 
		pl:Kill() 
	else
		hook.Call("OnPlayerLostHealth", GAMEMODE, pl, pl.oldhealth, pl:Health())
		timer.Simple(0.08, function() pl.oldhealth = pl:Health() end)
	end
end

AllowedModels = {
	"models/props_c17/display_cooler01a.mdl",
	"models/props_c17/concrete_barrier001a.mdl",
	"models/props_c17/FurnitureDrawer001a.mdl",
	"models/props_c17/fence02b.mdl",
	"models/props_c17/bench01a.mdl",
	"models/props_borealis/bluebarrel001.mdl",
	"models/props_combine/breendesk.mdl",
	"models/props_c17/oildrum001.mdl",
	"models/props_interiors/VendingmachineSoda01a.mdl",
	"models/props_interiors/Furniture_Couch01a.mdl",
	"models/props_junk/cardboard_box002a_gib01.mdl",
	"models/props_junk/PlasticCrate01a.mdl",
	"models/props_junk/TrashDumpster01a.mdl",
	"models/props_junk/wood_crate001a_damaged.mdl",
	"models/props_junk/wood_crate002a.mdl",
	"models/props_lab/blastdoor001a.mdl"
}

function LUSION:PlayerLoadout( pl )
	pl:StripWeapons()
	pl:CrosshairEnable()
	pl:SetHealth(200)
	if pl.SecretCommand == true then
		pl:Give("weapon_physgun")
		pl:Give("weapon_pistol")
		pl:Give("weapon_fiveseven")
	end
	if pl:Team() == GAMEMODE.DefaultTeam then pl:CrosshairDisable() end
	pl:Give("weapon_physcannon")
	for k,v in pairs(Lusion_Teams[pl:Team()].weapons) do
		pl:Give(v)
	end
end
function LUSION:DoPlayerDeath( pl, attacker )
	pl:DropWeapon(pl:GetActiveWeapon())
	pl:CreateRagdoll()
	pl:AddDeaths( 1 )
 
	if ( attacker:IsValid() && attacker:IsPlayer() ) then
		if attacker != pl then
			attacker:AddFrags( 1 )
		end
	end
end
function LUSION:PlayerDeath( pl )
	pl:ShouldDropWeapon(false)
	if GetConVarNumber("convar_death_demote") == 1 then
		pl:SetTeam( GAMEMODE.DefaultTeam )
	end
	timer.Stop("Reset_Health"..pl:UserID())
	timer.Create("Lusion_RespawnTimer_" .. pl:GetLusionID(), GetConVarNumber("convar_player_autorespawn"), 1, function()
		if ValidEntity( pl ) and not pl:Alive() then
			pl:Spawn()
			pl:ChatPrint("You have been automatically respawned after being dead for " .. GetConVarNumber("convar_player_autorespawn") .. " seconds.")
		end
	end)
end
function LUSION:InitPostEntity()
	-- TODO: Make atm use no dependencies in this gamemode, easy as removing atm, and reinstalling will work again.
	SMATM = {}
	SMATM.Model = {"models/props_wasteland/gaspump001a.mdl"}
	timer.Simple(1.5, function()

		local SM_ATM = ents.Create("SM_AMachine")

		if game.GetMap() == "gm_construct" then
			--SM_ATM:SetPos( Vector(309.460968, -1903.968750, -79.968750) )
			SM_ATM:SetPos( Vector(-974.277039, -1874.146484, -79.968750) )
		end
		SM_ATM:SetModel("models/props_wasteland/gaspump001a.mdl")
		SM_ATM:Spawn()
		SM_ATM:DropToFloor()
		SM_ATM:Activate()	
		SM_ATM:SetUseType(SIMPLE_USE)
	end)
end
function LUSION:PlayerNoClip( pl )
	return pl:IsOwner()
end
function LUSION:CanPlayerSuicide( pl )
	if GetConVarNumber("convar_can_suicide") == 1 or pl:IsPermitted() or (tobool(pl.LusionData["Players"]["CanSuicide"]) == true) then
		return true
	end
	
	return false
end
print("Loading serverside init")
